
#include <cmath>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <set>
#include "def.h"

using namespace std;

#include "Mutex.h"
#include "Cond.h"
#include "BiContainer.h"
#include "Lockable.h"
#include "VarCol.h"
#include "Formattable.h"
#include "TableState.h"	
#include "Table.h"
#include "TableList.h"	

TableList::TableList () {
 tables.reserve ( 200 ); /* TODO: load this parameter from conf */
}

Table *TableList::openTable (const string& tableName) {

 tableListMutex.lock ();

 if (tables.size() == 200) {
  serverError ( ERR_MAX_TABLES_REACHED );
  tableListMutex.unlock ();
  return NULL;
 }

 map<string, int>::iterator tableNamesItr = tableNames.find ( tableName );

 if (tableNamesItr == tableNames.end ()) {
  Table newTable ( tableName );

  tables.push_back ( newTable );
  refCount.push_back (1);
  tableNames.insert ( pair<string, int> (tableName, tables.size() - 1) );

  tableListMutex.unlock ();
  return tables.back();
 }
 else {
  refCount [ tableNamesItr->second ] += 1;

  tableListMutex.unlock ();

  return (tables + tableNamesItr->second);
 }
}

bool TableList::closeTable (const string& tableName) {
 tableListMutex.lock ();

 map<string, int>::iterator tableNamesItr = tableNames.find ( tableName );

 if (tableNamesItr == tableNames.end()) {
  tableListMutex.unlock ();
  return false;
 }
 else  {
  refCount [tableNamesItr->second] -= 1;
 
  if (refCount [tableNamesItr->second] == 0) {
   tables.erase     (tables.begin()   + tableNamesItr->second);
   refCount.erase   (refCount.begin() + tableNamesItr->second);
   tableNames.erase (tableNamesItr);
  }

  tableListMutex.unlock ();
 }
}
